package com.qingcheng.task;

import com.qingcheng.dao.SeckillGoodsMapper;
import com.qingcheng.pojo.seckill.SeckillGood;
import com.qingcheng.pojo.seckill.SeckillOrder;
import com.qingcheng.pojo.seckill.SeckillStatus;
import com.qingcheng.utils.CacheKey;
import com.qingcheng.utils.IdWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * Created by yuanxin
 * Date:2019/7/23
 * Time:20:33
 * 多线程异步操作类
 */
@Component
public class MultiThreadingCreateOrder {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;
    @Autowired
    private IdWorker idWorker;

    /**
     * 下单操作
     */
    @Async
    public void createOrder() {
        try {
            System.out.println("准备执行...");
            Thread.sleep(10000);
            SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps(CacheKey.SECKILLORDERQUEUE).rightPop();


            //用户抢单数据
            Long id = seckillStatus.getGoodsId();
            String time = seckillStatus.getTime();
            String username = seckillStatus.getUsername();

            //获取队列中的商品id
            Object sid = redisTemplate.boundListOps(CacheKey.SECKILLGOODSCOUNTLIST_.toString() + id).rightPop();
            //售罄
            if (sid == null) {
                clearQueue(seckillStatus);
                throw new RuntimeException("已售罄");
            }

            String key = "SeckillGoods_" + time;
            //获取商品数据
            SeckillGood good = (SeckillGood) redisTemplate.boundHashOps(key).get(id);
            Thread.sleep(10000);
            System.out.println(username + Thread.currentThread().getId() + "-----查询到商品库存" + good.getStockCount());
            if (good == null || good.getStockCount() <= 0) {
                throw new RuntimeException("已售罄!");
            }
            //如果有库存，则创建秒杀商品订单
            SeckillOrder seckillOrder = new SeckillOrder();
            seckillOrder.setId(idWorker.nextId());
            seckillOrder.setSeckillId(id);
            seckillOrder.setMoney(good.getCostPrice());
            seckillOrder.setUserId(username);
            seckillOrder.setSellerId(good.getSellerId());
            seckillOrder.setCreateTime(new Date());
            seckillOrder.setStatus("0");

            //将秒杀订单存入到Redis中
            redisTemplate.boundHashOps("SeckillOrder").put(username, seckillOrder);
            seckillStatus.setOrderId(seckillOrder.getId());
            seckillStatus.setMoney(seckillOrder.getMoney().floatValue());
            seckillStatus.setStatus(2);
            redisTemplate.boundHashOps(CacheKey.USERQUEUESTATUS).put(username, seckillStatus);

            //商品库存-1
            Long surplusCount = redisTemplate.boundHashOps(CacheKey.SECKILLGOODSCOUNT).increment(id, -1);
            good.setStockCount(surplusCount.intValue());
            //判断当前商品是否还有库存
            if (surplusCount <= 0) {
                //并且将商品数据同步到MySQL中
                seckillGoodsMapper.updateByPrimaryKeySelective(good);
                //如果没有库存,则清空Redis缓存中该商品
                redisTemplate.boundHashOps(key).delete(id);
            } else {
                //如果有库存，则直数据重置到Reids中
                redisTemplate.boundHashOps(key).put(id, good);
            }

            System.out.println("执行完成");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 清理用户排队信息
     *
     * @param seckillStatus
     */
    private void clearQueue(SeckillStatus seckillStatus) {
        //清理重复下单信息
        redisTemplate.boundHashOps(CacheKey.USERQUEUECOUNT).delete(seckillStatus.getUsername());
        //清理排队存储信息
        redisTemplate.boundHashOps(CacheKey.USERQUEUESTATUS).delete(seckillStatus.getUsername());
    }
}
